home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / video / fly8111-.000 / fly8111- / fly8 / COMMON / fly8udp.c < prev    next >
C/C++ Source or Header  |  1979-12-31  |  7KB  |  327 lines

  1. /* --------------------------------- fly8udp.c ------------------------------ */
  2.  
  3. /* This is part of the flight simulator 'fly8'.
  4.  * Author: Eyal Lebedinsky (eyal@ise.canberra.edu.au).
  5. */
  6.  
  7. /* This server is needed when using the udp driver.
  8. */
  9.  
  10. #include "config.h"
  11.  
  12. #ifdef HAVE_UDP
  13.  
  14. #include <stdio.h>
  15. #include <time.h>
  16. #include <sys/timeb.h>
  17. #define PHEAD        msg
  18. #include "fly8udp.h"
  19.  
  20.  
  21. static char    admin[LADDRESS] = ADMIN_ADDR;
  22.  
  23. #define FLY8_TTL    10        /* 10 seconds idle time allowed */
  24.  
  25. struct client {
  26.     struct client        *next;
  27.     struct sockaddr_in    addr;
  28.     time_t            timeout;
  29. };
  30.  
  31. static struct client    *clients = 0;    /* active clients list */
  32. static int        nclients = 0;    /* active clients count */
  33. static char        *pname = 0;    /* program name */
  34.  
  35. static long        nin = 0, ninb = 0, nout = 0, noutb = 0;
  36. static long        errs[10] = {0};
  37.  
  38. extern char *
  39. my_ctime (void)
  40. {
  41.     time_t    tm;
  42.     char    *t;
  43.  
  44.     tm = time (0);
  45.     t = ctime (&tm);
  46.     t[strlen (t) - 1] = '\0';    /* kill NewLine */
  47.     return (t);
  48. }
  49.  
  50. /* If this packet is from a new client then register it.
  51. */
  52. static void
  53. add_client (struct sockaddr_in *sin, int sinlen)
  54. {
  55.     struct client    *p;
  56.  
  57.     for (p = clients; p; p = p->next) {
  58.         if (p->addr.sin_addr.s_addr == sin->sin_addr.s_addr &&
  59.             p->addr.sin_port        == sin->sin_port)
  60.             break;
  61.     }
  62.     if (!p) {
  63.         p = (struct client *)malloc (sizeof (*p));
  64.         if (!p) {
  65.             ++errs[0];
  66.             return;            /* no mem */
  67.         }
  68.         memcpy (&p->addr, sin, sinlen);
  69.         p->next = clients;
  70.         clients = p;
  71.         printf ("%s: %s added %08lx:%04x\n", 
  72.             pname, my_ctime (), ntohl (p->addr.sin_addr.s_addr),
  73.             ntohs (p->addr.sin_port));
  74.         fflush (stdout);
  75.         ++nclients;
  76.     }
  77.     p->timeout = time (0) + FLY8_TTL;
  78. }
  79.  
  80. /* Echo an incomming packet to all other registered clients.
  81. */
  82. static void
  83. echo_clients (int fd, struct sockaddr_in *sin, char *msg, int len)
  84. {
  85.     struct client    *p, *pp, *del;
  86.     time_t        now;
  87.     int        private;
  88.  
  89.     
  90.     private = len && memcmp (PHTO, "\377\377\377\377\377\377", LADDRESS);
  91.     now = time (0);
  92.  
  93.     for (pp = 0, p = clients; p;) {
  94.         if (p->timeout < now) {
  95.             printf ("%s: %s timed %08lx:%04x\n", 
  96.                 pname, my_ctime (),
  97.                 ntohl (p->addr.sin_addr.s_addr),
  98.                 ntohs (p->addr.sin_port));
  99.             fflush (stdout);
  100.             --nclients;
  101.             del = p;
  102.             p = p->next;
  103.             if (pp)
  104.                 pp->next = p;
  105.             else
  106.                 clients = p;
  107.             free (del);
  108.             continue;
  109.         }
  110.  
  111. /* do not echo if no input, or to the packet source, or to wronf dest for
  112.  * private packets.
  113. */
  114.         if (!len ||
  115.             (p->addr.sin_addr.s_addr == sin->sin_addr.s_addr &&
  116.              p->addr.sin_port        == sin->sin_port) ||
  117.             (private &&
  118.              (memcmp (PHTO,   (char *)&p->addr.sin_addr.s_addr, 4) ||
  119.               memcmp (PHTO+4, (char *)&p->addr.sin_port, 2))))
  120.             ;
  121.         else if (sendto (fd, msg, len, 0, (struct sockaddr *)&p->addr, 
  122.                         sizeof (p->addr)) != len) {
  123. #ifdef FLY8_DEBUG
  124.             printf ("%s sendto() failed to %08lx:%04x\n", 
  125.                 pname, ntohl (p->addr.sin_addr.s_addr),
  126.                 ntohs (p->addr.sin_port));
  127.             fflush (stdout);
  128. #endif
  129.             ++errs[1];
  130.         } else {
  131. #ifdef FLY8_DEBUG
  132.             printf ("%s %3u bytes echo %08lx:%04x\n", 
  133.                 pname, len, ntohl (p->addr.sin_addr.s_addr),
  134.                 ntohs (p->addr.sin_port));
  135.             fflush (stdout);
  136. #endif
  137.             ++nout;
  138.             noutb += len;
  139.         }
  140.         pp = p;
  141.         p = pp->next;
  142.     }
  143. }
  144.  
  145. struct svr_stats {
  146.     int    msgid;
  147. #define    SVM_STATS    0x0001
  148.     int    nclients;
  149.     long    nin;
  150.     long    ninb;
  151.     long    nout;
  152.     long    noutb;
  153.     long    ernomem;
  154.     long    ersend;
  155. };
  156.  
  157. static char msg1[] = "SSSSSSDDDDDDLLstats received";
  158.  
  159. static void
  160. show_stats (int fd, struct sockaddr_in *p)
  161. {
  162.     if (p) {
  163. #if 0
  164.         struct svr_stats    stats;
  165.  
  166.         if (sendto (fd, &svr_stats, sizeof(svr_stats), 0, 
  167.             (struct sockaddr *)&p->addr, sizeof (p->addr)) != len){
  168. #else
  169.         if (sendto (fd, msg1, sizeof(msg1), 0, 
  170.             (struct sockaddr *)p, sizeof (*p)) != sizeof(msg1)){
  171. #endif
  172.         }
  173.     }
  174.  
  175.     printf ("%s: %s stats:\n", pname, my_ctime ());
  176.     printf ("clients:      %d\n",  nclients);
  177.     printf ("messages in:  %ld\n", nin);
  178.     printf ("bytes    in:  %ld\n", ninb);
  179.     printf ("messages out: %ld\n", nout);
  180.     printf ("bytes    out: %ld\n", noutb);
  181.     printf ("add no mem:   %ld\n", errs[0]);
  182.     printf ("send failed:  %ld\n", errs[1]);
  183.     printf ("recv failed:  %ld\n", errs[2]);
  184.     fflush (stdout);
  185. }
  186.  
  187. static char msg2[] = "bad admin request received";
  188.  
  189. static void
  190. show_badmin (int fd, struct sockaddr_in *p)
  191. {
  192.     if (p) {
  193.         if (sendto (fd, msg2, sizeof(msg2), 0, 
  194.             (struct sockaddr *)p, sizeof (*p)) != sizeof(msg1)){
  195.         }
  196.     }
  197. }
  198.  
  199. static char    FAR msg[1500];            /* message buffer */
  200.  
  201. int
  202. main (int argc, char *argv[])
  203. {
  204.     int            fd;
  205.     struct sockaddr_in    sin;
  206.     char            *protoname;
  207.     struct protoent        *proto;
  208.     int            sinlen;        /* address length */
  209.     int            n;        /* incomming message length */
  210.  
  211.     pname = argv[0];
  212.  
  213. #ifdef WATTCP
  214.     sock_init ();
  215.  
  216.     if ((fd = socket (AF_INET, SOCK_FLY8, IPPROTO_UDP)) < 0) {
  217. #else
  218.     protoname = "udp";
  219.     if ((proto = getprotobyname (protoname)) == NULL) {
  220.         printf ("%s: %s getprotobyname(%s) failed: %s\n", 
  221.             pname, my_ctime (), protoname, strerror (errno));
  222.         fflush (stdout);
  223.         exit (1);
  224.     }
  225.     if ((fd = socket (AF_INET, SOCK_FLY8, proto->p_proto)) < 0) {
  226. #endif
  227.         printf ("%s: %s socket() failed: %s\n",
  228.             pname, my_ctime (), strerror (errno));
  229.         fflush (stdout);
  230.         exit (1);
  231.     }
  232.  
  233.     memset (&sin, 0, sizeof (sin));
  234.     sin.sin_family      = AF_INET;
  235.     sin.sin_addr.s_addr = htonl (INADDR_ANY);
  236.     sin.sin_port        = htons (IPPORT_FLY8);
  237.  
  238.     if (bind (fd, (struct sockaddr *) &sin, sizeof (struct sockaddr)) < 0) {
  239.         printf ("%s: %s bind() failed: %s\n",
  240.             pname, my_ctime (), strerror (errno));
  241.         fflush (stdout);
  242.         exit (1);
  243.     }
  244.  
  245.     for (;;) {
  246.         sinlen = sizeof (struct sockaddr);
  247.         if ((n = recvfrom (fd, msg, sizeof(msg), 0,
  248.                 (struct sockaddr *)&sin, &sinlen)) < 0) {
  249.             printf ("%s: %s recvfrom() failed: %s\n", 
  250.                 pname, my_ctime (), strerror (errno));
  251.             fflush (stdout);
  252.             ++errs[2];
  253.             continue;
  254.         }
  255. #ifdef WATTCP
  256.         if (0 == n) {
  257.             echo_clients (fd, NULL, msg, 0);
  258.             continue;
  259.         }
  260. #endif
  261. #ifdef FLY8_DEBUG
  262.         printf ("%s %ld: %3u bytes from %08lx:%04x\n", 
  263.             pname, nin, n, ntohl (sin.sin_addr.s_addr),
  264.             ntohs (sin.sin_port));
  265.         fflush (stdout);
  266. #endif
  267.  
  268. /* Handle administrative requests first.
  269. */
  270.         if (!memcmp (PHFROM, admin, LADDRESS)) {
  271.             echo_clients (fd, NULL, msg, 0);
  272.             if (!strcmp ("shutdown\n", PHDATA)) {
  273.                 printf ("%s: %s shutdown requested\n",
  274.                     pname, my_ctime ());
  275.                 break;
  276.             }
  277.  
  278.             if (!strcmp ("stats\n", PHDATA)) {
  279.                 show_stats (fd, &sin);
  280.                 continue;
  281.             }
  282.             show_badmin (fd, &sin);
  283.             continue;
  284.         }
  285.  
  286. /* This is a client packet, pass it on.
  287. */
  288.         ++nin;
  289.         ninb += n;
  290.  
  291. /* Fill in the internal 'from address' in the packet since Fly8 has some
  292.  * trouble getting it right. If it is already filled in then this msg came
  293.  * from another server.
  294. */
  295.         if (!memcmp (PHFROM, "\0\0\0\0\0\0", LADDRESS)) {
  296.             memcpy (PHFROM, (char *)&sin.sin_addr.s_addr, 4);
  297.             memcpy (PHFROM+4, (char *)&sin.sin_port, 2);
  298.         }
  299.  
  300.         add_client (&sin, sinlen);
  301.         echo_clients (fd, &sin, msg, n);
  302.     }
  303.     fflush (stdout);
  304.  
  305. #ifdef WATTCP
  306.     n_close (fd);
  307. #else
  308.     close (fd);
  309. #endif
  310.  
  311.     show_stats (0, NULL);
  312.  
  313.     exit (0);
  314.     return (0);
  315. }
  316.  
  317. #else
  318.  
  319. int
  320. main (int argc, char *argv[])
  321. {
  322.     printf ("upd not available\n");
  323.     exit (0);
  324. }
  325.  
  326. #endif
  327.